home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / fviewsrc.zip / UNPAK.C < prev    next >
C/C++ Source or Header  |  1993-01-04  |  8KB  |  236 lines

  1. /*--------------------------------------------------------------------------*/
  2. /*                                                                          */
  3. /* Copyright 1989, Doug Boone.  FidoNet 119/5                               */
  4. /*                              (916) 893-9019 Data                         */
  5. /*                              (916) 891-0748 voice                        */
  6. /*                              P.O. Box 5108, Chico, CA. 95928             */
  7. /*                                                                          */
  8. /* This program is not for sale. It is for the free use with Opus systems.  */
  9. /* You may not sell it in ANY way. If you have an access charge to your     */
  10. /* Bulletin Board, consider this to be like Opus, you can ONLY make it      */
  11. /* available for download in an open area, where non-members can get access */
  12. /*                                                                          */
  13. /* If you need to modify this source code, please send me a copy of the     */
  14. /* changes you've made so that everyone can share in the updates.           */
  15. /*                                                                          */
  16. /* "Don't rip me off!" -- Tom Jennings, FidoNet's founder                   */
  17. /*                                                                          */
  18. /*--------------------------------------------------------------------------*/
  19.  
  20. #include <io.h>
  21. #include <stdlib.h>
  22. #include <stdio.h>
  23. #include <conio.h>
  24. #include <ctype.h>
  25. #include <fcntl.h>
  26. #include <sys\stat.h>
  27. #include <string.h>
  28. #include <time.h>
  29. #include "compress.h"
  30. #define MARKER_VALUE 26
  31. #define BUFFER_SIZE  32768
  32.  
  33. extern  FILE    *Log_fp;
  34. void    unstore(int,int,long);
  35.  
  36. typedef struct {   /*  ARC file header record definition  */
  37.           char            marker;   /* should always be MARKER_VALUE */
  38.           char            packtype;
  39.           char            name[13];
  40.           long            size;
  41.           long                 datetime;
  42.           unsigned        crc;
  43.           long            length;
  44.          }  compress_header;
  45.  
  46. void        *variables;
  47. unsigned    variable_size;
  48. char        *input_buffer;
  49. char        *output_buffer;
  50.  
  51. unsigned expand_file(int input_handle, int output_handle, long size, int type)
  52.  {
  53.   unsigned input_remaining; /* data remaining in input block */
  54.   unsigned input_size;      /* size of current pass */
  55.   unsigned buf_pos;         /* position in input buffer */
  56.   long     total_input;     /* total input processed */
  57.   long     total_output;    /* total output processed */
  58.   unsigned output_size;     /* size of current output block */
  59.   int      done;            /* boolean flag when finished */
  60.   int      end_of_input;    /* boolean flag for last input block */
  61.   int       n;
  62.  
  63.   total_input = 0;   /* zero counters */
  64.   total_output = 0;
  65.  
  66.   switch(type) {
  67.     case 10:    init_expand_Crush(variables);  /* initialize variable area */
  68.                 break;
  69.  
  70.     case  9:    expand_LZW_size();
  71.                 init_expand_LZW(variables,13,0);
  72.                 break;
  73.  
  74.     case  8:    expand_LZW_size();
  75.                 read(input_handle,input_buffer,1);
  76.                 n = input_buffer[0];
  77.                 init_expand_LZW(variables,n,1);
  78.                 break;
  79.  
  80.     case  3:    init_expand_RLE();
  81.                 break;
  82.  
  83.     case  2:
  84.     case  1:    unstore(input_handle,output_handle,size);
  85.                 return(1);
  86.  
  87.     } /* End of switch */
  88.  
  89.   do {  /* for each input block */
  90.       /* read the block */
  91.     input_remaining = read(input_handle, input_buffer, BUFFER_SIZE);
  92.       /* check if buffered input larger than file to be expanded */
  93.     if (total_input + input_remaining > size) {
  94.       input_remaining = size - total_input;
  95.      }
  96.  
  97.     total_input += input_remaining;  /* increment counter */
  98.     end_of_input = total_input == size;  /* flag if last input block */
  99.     buf_pos = 0;                        /* set buffer position to start */
  100.     do {
  101.       input_size = input_remaining; /* maximum input = remaining input */
  102.       output_size = BUFFER_SIZE;    /* maximum output = size of buffer */
  103.       switch(type) {
  104.         case 10:    done = expand_Crush(input_buffer + buf_pos, &input_size,
  105.                         output_buffer, &output_size, variables, end_of_input);
  106.                     break;
  107.  
  108.         case  9:    done = expand_LZW(input_buffer + buf_pos, &input_size,
  109.                         output_buffer, &output_size, variables, end_of_input);
  110.                     break;
  111.  
  112.         case  8:    done = expand_LZW(input_buffer + buf_pos, &input_size,
  113.                         output_buffer, &output_size, variables, end_of_input);
  114.                     break;
  115.  
  116.         case  3:    done = expand_RLE(input_buffer + buf_pos, &input_size,
  117.                         output_buffer, &output_size, end_of_input);
  118.                     break;
  119.         }        /* End of switch */
  120.  
  121.  
  122.       buf_pos += input_size;         /* move pointer */
  123.       input_remaining -= input_size; /* decrement input remaining */
  124.       total_output += output_size;   /* increment output counter */
  125.       write(output_handle, output_buffer, output_size); /* write out buffer */
  126.      } while(input_remaining);
  127.    } while (!done);
  128.    return(done);
  129.  }
  130.  
  131.  
  132. int init_buffers(void)  /* allocate buffers + variable area */
  133.  {
  134.   variable_size = expand_Crush_size();
  135.   if ((variables = malloc(variable_size)) == NULL) {
  136.     fprintf(Log_fp,"Not enough memory for Crushing variables\n");
  137.     return(2);
  138.    }
  139.   if ((input_buffer = (char *) malloc(BUFFER_SIZE)) == NULL) {
  140.     fprintf(Log_fp,"Not enough memory for input buffer\n");
  141.     return(2);
  142.    }
  143.   if ((output_buffer = (char *) malloc(BUFFER_SIZE)) == NULL) {
  144.     fprintf(Log_fp,"Not enough memory for output buffer\n");
  145.     return(2);
  146.    }
  147.    return(0);
  148.  }
  149.  
  150. int unpak(char *source,char *to)
  151.  {
  152.   compress_header header;        /* header describing files */
  153.   int           input_handle;
  154.   int           output_handle;
  155.   long          next_file;     /* position in input file of next header */
  156.   char          *name;
  157.   int           result = 1;
  158.   unsigned        check = 255;
  159.  
  160.     if ((name = strrchr(to,'\\')) == NULL)
  161.         name = to;
  162.     else
  163.         name++;
  164.     if ((result = init_buffers()) !=0)
  165.         return(2);
  166.  
  167.     if ((input_handle = open(source, O_RDONLY | O_BINARY)) < 0) {
  168.         fprintf(Log_fp,"could not open %s\n",source);
  169.         return(1);
  170.     }
  171.  
  172.  
  173.     _fmode = O_BINARY;
  174.     next_file = 0;    /* start at begining of file */
  175.     do {
  176.         lseek(input_handle, next_file, SEEK_SET); /* move to next header */
  177.  
  178.         /* read header */
  179.         if (read(input_handle, &header, sizeof(header)) < sizeof(header))
  180.             break;  /* we didn't get a full header, so quit. */
  181.  
  182.         if (header.marker != MARKER_VALUE)  /* first byte is always ^Z */
  183.             break;
  184.  
  185.         if (header.packtype == 0)  /* last header */
  186.             break;
  187.  
  188.         /* set position of next file */
  189.         next_file = tell(input_handle) + header.size;
  190.  
  191.         if (strcmp(header.name,name) == 0) {
  192.             if ((output_handle = creat(to, S_IREAD | S_IWRITE)) < 0) {
  193.                 fprintf(Log_fp,"Could not create %s\n",to);
  194.                 return(1);
  195.                 }
  196.             result = 1;
  197.             check = expand_file(input_handle, output_handle,
  198.                 header.size,header.packtype);
  199.             close(output_handle);
  200.             }        /* End of name match */
  201.  
  202.         } while (result == 0);  /* until we run out of file, actually. */
  203.   close(input_handle);
  204.   return(check-1);
  205.  }
  206.  
  207. void unstore(int input_handle,int output_handle,long size)
  208. {
  209.     char        *buf;
  210.     unsigned    done;
  211.     unsigned    do_what;
  212.  
  213.     if (size < BUFFER_SIZE) {
  214.         do_what = (unsigned) size;
  215.         buf = (char *) malloc(do_what);
  216.         read(input_handle,buf,do_what);
  217.         write(output_handle,buf,do_what);
  218.         free(buf);
  219.         }
  220.     else {
  221.         do_what = BUFFER_SIZE;
  222.         buf = (char *) malloc(BUFFER_SIZE);
  223.         while (size > 0L) {
  224.             done = read(input_handle,buf,do_what);
  225.             write(output_handle,buf,do_what);
  226.             size -= (long) done;
  227.             if (size < BUFFER_SIZE)
  228.                 do_what = (unsigned) size;
  229.             }
  230.         free(buf);
  231.         }
  232.     return;
  233. }
  234.  
  235.         
  236.